package com.ruoyi.buy.service.impl;

import com.ruoyi.buy.domain.entity.PO.InvInventoryInfo;
import com.ruoyi.buy.domain.entity.PO.InvTransboundBill;
import com.ruoyi.buy.domain.entity.PO.InvTransboundBillItem;
import com.ruoyi.buy.domain.entity.PO.InvWarehouseInfo;
import com.ruoyi.buy.domain.entity.inv0005.Inv0005InvDataDto;
import com.ruoyi.buy.domain.entity.inv0009.Inv0009UpdateByIdVO;
import com.ruoyi.buy.domain.entity.inv0009.Inv0009WareHouseList;
import com.ruoyi.buy.mapper.PO.*;
import com.ruoyi.buy.service.ICommonService;
import com.ruoyi.buy.service.IInvTransboundBillService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 调拨单Service业务层处理
 * 
 * @author panghai
 * @date 2024-01-09
 */
@Service
@Transactional
public class InvTransboundBillServiceImpl implements IInvTransboundBillService
{
    @Resource
    private InvTransboundBillMapper invTransboundBillMapper;

    @Resource
    private InvTransboundBillItemMapper invTransboundBillItemMapper;

    @Resource
    private ICommonService commonService;

    @Resource
    private InvWarehouseInfoMapper invWarehouseInfoMapper;

    @Resource
    private InvOutboundBillMapper invOutboundBillMapper;

    @Resource
    private InvInventoryInfoMapper invInventoryInfoMapper;

    /**
     * 查询调拨单
     * 
     * @param id 调拨单主键
     * @return 调拨单
     */
    @Override
    public Inv0009UpdateByIdVO selectInvTransboundBillById(Long id)
    {
        Inv0009UpdateByIdVO result = new Inv0009UpdateByIdVO();
        result.setInvTransboundBill(invTransboundBillMapper.selectInvTransboundBillById(id));

        InvTransboundBillItem query = new InvTransboundBillItem();
        query.setnMainId(id);
        List<InvTransboundBillItem> invTransboundBillItemList = this.invTransboundBillItemMapper.selectInvTransboundBillItemList(query);
        result.setInvTransboundBillItemList(invTransboundBillItemList);
        return result;
    }

    /**
     * 查询调拨单列表
     * 
     * @param invTransboundBill 调拨单
     * @return 调拨单
     */
    @Override
    public List<InvTransboundBill> selectInvTransboundBillList(InvTransboundBill invTransboundBill)
    {
        return invTransboundBillMapper.selectInvTransboundBillList(invTransboundBill);
    }

    /**
     * 新增调拨单
     * 
     * @param para 调拨单
     * @return 结果
     */
    @Override
    public int insertInvTransboundBill(Inv0009UpdateByIdVO para)
    {

        //先主表
        InvTransboundBill invTransboundBill = para.getInvTransboundBill();
        invTransboundBill.setIotype("O");
        invTransboundBill.setvType("ODB");
        invTransboundBill.setStatus("0");
        invTransboundBill.setCreateTime(DateUtils.getNowDate());
        invTransboundBill.setCreateBy(commonService.getUsername());
        invTransboundBill.setvBillNo(commonService.getNo("DB"));
        invTransboundBill.setOprBy(commonService.getUsername());
        this.invTransboundBillMapper.insertInvTransboundBill(invTransboundBill);
        invTransboundBill = this.invTransboundBillMapper.selectInvTransboundBillList(invTransboundBill).get(0);
        Long id = invTransboundBill.getId();

        //再子表
        List<InvTransboundBillItem> invTransboundBillItemList = para.getInvTransboundBillItemList();

        for (InvTransboundBillItem item: invTransboundBillItemList
        ) {
            item.setnMainId(id);
            item.setCreateTime(DateUtils.getNowDate());
            item.setCreateBy(commonService.getUsername());
            item.setvOpr(commonService.getUsername());
            this.invTransboundBillItemMapper.insertInvTransboundBillItem(item);
        }
        return 1;
    }

    /**
     * 修改调拨单
     * 
     * @param para 调拨单
     * @return 结果
     */
    @Override
    public int updateInvTransboundBill(Inv0009UpdateByIdVO para)
    {
        InvTransboundBill invTransboundBill = para.getInvTransboundBill();
        invTransboundBill.setUpdateTime(DateUtils.getNowDate());
        invTransboundBill.setUpdateBy(commonService.getUsername());
        invTransboundBillMapper.updateInvTransboundBill(invTransboundBill);

        Long id = invTransboundBill.getId();
        //再子表
        List<InvTransboundBillItem> invTransboundBillItemList = para.getInvTransboundBillItemList();
        for (InvTransboundBillItem item: invTransboundBillItemList
        ) {
            if (item.getId() == null || item.getId() == 0){
                item.setnMainId(id);
                item.setCreateTime(DateUtils.getNowDate());
                item.setCreateBy(commonService.getUsername());
                item.setvOpr(commonService.getUsername());
                this.invTransboundBillItemMapper.insertInvTransboundBillItem(item);
            }else{
                InvTransboundBillItem search = new InvTransboundBillItem();
                search = this.invTransboundBillItemMapper.selectInvTransboundBillItemById(item.getId());
                if(search.getnQty() != item.getnQty()){
                    this.invTransboundBillItemMapper.updateInvTransboundBillItem(item);
                }
            }
        }
        return 1;
    }

    /**
     * 批量删除调拨单
     * 
     * @param ids 需要删除的调拨单主键
     * @return 结果
     */
    @Override
    public int deleteInvTransboundBillByIds(Long[] ids)
    {
        return invTransboundBillMapper.deleteInvTransboundBillByIds(ids);
    }

    /**
     * 删除调拨单信息
     * 
     * @param id 调拨单主键
     * @return 结果
     */
    @Override
    public int deleteInvTransboundBillById(Long id)
    {
        return invTransboundBillMapper.deleteInvTransboundBillById(id);
    }

    @Override
    public Inv0009WareHouseList getWhlist() {
        Inv0009WareHouseList result = new Inv0009WareHouseList();
        InvWarehouseInfo query = new InvWarehouseInfo();
        query.setParentId(0L);
        List<InvWarehouseInfo> list = this.invWarehouseInfoMapper.selectInvWarehouseInfoList(query);
        List<InvWarehouseInfo> lWhlist = list.stream().filter(s->s.getWhType().equals("L")).collect(Collectors.toList());
        List<InvWarehouseInfo> oWhlist = list.stream().filter(s->s.getWhType().equals("V")).collect(Collectors.toList());
        result.setlWhlist(lWhlist);
        result.setoWhlist(oWhlist);
        return result;
    }

    @Override
    public int excuteTrans(Inv0009UpdateByIdVO para) throws Exception{

        //库存数量校验
        List<InvTransboundBillItem> invOutboundBillItemList = para.getInvTransboundBillItemList();
        for (InvTransboundBillItem item:invOutboundBillItemList
        ) {
            BigDecimal nQty = item.getnQty();
            Inv0005InvDataDto inv0005InvDataDto = new Inv0005InvDataDto();
            BeanUtils.copyBeanProp(inv0005InvDataDto,item);
            inv0005InvDataDto.setnQty(null);
            Inv0005InvDataDto nowData = this.invOutboundBillMapper.getInvDataList(inv0005InvDataDto).get(0);
            if(nQty.compareTo(nowData.getnQty())>0){
                throw new ServiceException("物料:"+item.getvSpaName()+"库存数量不足，请确认");
            }
        }

        //保存主子表信息
        InvTransboundBill invTransboundBill = para.getInvTransboundBill();
        invTransboundBill.setStatus("1");
        para.setInvTransboundBill(invTransboundBill);
        this.updateInvTransboundBill(para);
        //先执行本地出库
        this.executeOut(para);
        //再执行项目仓入库
        return 1;
    }

    private void executeOut(Inv0009UpdateByIdVO para) throws Exception {
        List<InvTransboundBillItem> invTransboundBillItemList = para.getInvTransboundBillItemList();
        InvTransboundBill invTransboundBill = para.getInvTransboundBill();
        //拆先入先出
        List<InvTransboundBillItem> list = new ArrayList<>();
        for (InvTransboundBillItem item:invTransboundBillItemList
        ) {
            InvInventoryInfo invInventoryInfo = new InvInventoryInfo();
            BeanUtils.copyBeanProp(invInventoryInfo,item);
            List<InvInventoryInfo> invInventoryInfos = this.invInventoryInfoMapper.selectInvInventoryInfoListOrderByLot(invInventoryInfo);
            BigDecimal nQty = item.getnQty();
            for (InvInventoryInfo info:invInventoryInfos
            ) {
                if(nQty.compareTo(BigDecimal.ZERO)>0){
                    InvTransboundBillItem invTransboundBillItem = new InvTransboundBillItem();
                    BeanUtils.copyBeanProp(invTransboundBillItem,item);
                    if (nQty.compareTo(info.getnQty())>0){
                        nQty = nQty.subtract(info.getnQty());
                        invTransboundBillItem.setnQty(info.getnQty());
                    }else{
                        invTransboundBillItem.setnQty(nQty);
                        nQty = nQty.subtract(nQty);
                    }
                    invTransboundBillItem.setnPrice(info.getnPrice());
                    invTransboundBillItem.setvLotNo(info.getvLotNo());
                    invTransboundBillItem.setvContractNo(info.getvContractNo());
                    invTransboundBillItem.setvProjectNo(info.getvProjectNo());
                    list.add(invTransboundBillItem);
                }

            }
        }

        //改库存,先出库存,调拨出
        commonService.changeInventory(invTransboundBill,new ArrayList<>(list),"DBOUT");

        //改库存，再入库存
        Map<String,Long> getWHInfo = this.getWHInfo(para.getInvTransboundBill().getInWHId());
        Long nAreaId = getWHInfo.get("nAreaId");
        Long nLocationId = getWHInfo.get("nLocationId");

        for (InvTransboundBillItem item:list
             ) {
            item.setvAreaId(String.valueOf(nAreaId));
            item.setvLocationId(String.valueOf(nLocationId));
            item.setvWHId(String.valueOf(invTransboundBill.getInWHId()));
        }
        invTransboundBill.setvType("IDB");
        invTransboundBill.setIotype("I");
        //改库存,先出库存,调拨出
        commonService.changeInventory(invTransboundBill,new ArrayList<>(list),"DBIN");
    }

    private Map<String,Long> getWHInfo(Long nWHId) throws Exception {
        Long nAreaId = null;
        Long nLocationId = null;
        //先查一个调入仓库的库位号，调入库存只有一个库区一个库位
        InvWarehouseInfo search = new InvWarehouseInfo();
        search.setParentId(nWHId);
        List<InvWarehouseInfo> list = this.invWarehouseInfoMapper.selectInvWarehouseInfoList(search);
        if (list.isEmpty()){
            throw new Exception("该仓库下没有库区库位信息，请确认");
        }else{
            nAreaId = list.get(0).getId();
            search = new InvWarehouseInfo();
            search.setParentId(nAreaId);
            list = this.invWarehouseInfoMapper.selectInvWarehouseInfoList(search);
            if (list.isEmpty()){
                throw new Exception("该仓库下没有库区库位信息，请确认");
            }else{
                nLocationId = list.get(0).getId();
            }
        }
        Map<String,Long> result = new HashMap<>();
        result.put("nAreaId",nAreaId);
        result.put("nLocationId",nLocationId);
        return result;
    }
}
